package cn.wolfcode.wolf2w.business.service.impl;

import cn.wolfcode.wolf2w.business.api.RemoteDestinationService;
import cn.wolfcode.wolf2w.business.api.domain.Destination;
import cn.wolfcode.wolf2w.business.api.domain.Note;
import cn.wolfcode.wolf2w.business.mapper.NoteContentMapper;
import cn.wolfcode.wolf2w.business.mapper.NoteMapper;
import cn.wolfcode.wolf2w.business.query.NoteQuery;
import cn.wolfcode.wolf2w.business.service.INoteService;
import cn.wolfcode.wolf2w.business.util.DateUtil;
import cn.wolfcode.wolf2w.common.core.constant.SecurityConstants;
import cn.wolfcode.wolf2w.common.core.context.SecurityContextHolder;
import cn.wolfcode.wolf2w.common.core.domain.R;
import cn.wolfcode.wolf2w.common.redis.service.RedisService;
import cn.wolfcode.wolf2w.common.redis.util.RedisKeys;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * 旅游日记Service业务层处理
 * 
 * @author Tianluhuan
 * @date 2025-09-16
 */
@Service
@Transactional
public class NoteServiceImpl extends ServiceImpl<NoteMapper,Note> implements INoteService {

    @Autowired
    private NoteMapper noteMapper;
    @Autowired
    private RemoteDestinationService remoteDestinationService;
    @Autowired
    private NoteContentMapper  noteContentMapper;
    @Autowired
    private RedisService  redisService;

    @Override
    public IPage<Note> queryPage(NoteQuery qo) {
        IPage<Note> page = new Page<>(qo.getCurrentPage(), qo.getPageSize());
        QueryWrapper<Note> wrapper = new QueryWrapper<>();
        if (qo.getOrderType() != null){
            switch (qo.getTravelTimeType()){
                case 1:
                    wrapper.apply("MONTH(travel_time) in (1,2)");
                    break;
                case 2:
                    wrapper.apply("MONTH(travel_time) in (3,4)");
                    break;
                case 3:
                    wrapper.apply("MONTH(travel_time) in (5,6)");
                    break;
                case 4:
                    wrapper.apply("MONTH(travel_time) in (7,8)");
                    break;
                case 5:
                    wrapper.apply("MONTH(travel_time) in (9,10)");
                    break;
                case 6:
                    wrapper.apply("MONTH(travel_time) in (11,12)");
                    break;
                default:
                    break;
            }
        }

        if (qo.getConsumeType()!= null){
            switch (qo.getConsumeType()){
                case 1:
                    wrapper.between("avg_consume",1,999);
                    break;
                case 2:
                    wrapper.between("avg_consume",1000,6000);
                    break;
                case 3:
                    wrapper.between("avg_consume",6001,20000);
                    break;
                case 4:
                    wrapper.gt("avg_consume",20000);
                    break;
                default:
                    break;
            }
        }

        if (qo.getDayType()!= null){
            switch (qo.getDayType()){
                case 1:
                    wrapper.le("days",3);
                    break;
                case 2:
                    wrapper.between("days",4,7);
                    break;
                case 3:
                    wrapper.between("days",8,14);
                    break;
                case 4:
                    wrapper.ge("days",15);
                    break;
                default:
                    break;
            }
        }
        if (qo.getOrderType() != null){
            if (qo.getOrderType() == 1) {
                wrapper.orderByDesc("create_time");
            }else if (qo.getOrderType() == 2) {
                wrapper.orderByDesc("viewnum");
            }
        }
    return noteMapper.selectPage(page, wrapper);
    }

    @Override
    public void insert(Note note) {
        Destination one = remoteDestinationService.getOne(note.getDestId(), SecurityConstants.INNER).getData();
        note.setDestName(one.getName());
        note.setAuthorId(SecurityContextHolder.getUserId());
        note.setCreateTime(new Date());
        note.setUpdateTime(new Date());
        note.setViewnum(0L);
        note.setReplynum(0L);
        note.setFavornum(0L);
        note.setSharenum(0L);
        note.setThumbsupnum(0L);
        note.setStatus("0");
        noteMapper.insert(note);
        note.getContent().setId(note.getId());
        noteContentMapper.insert(note.getContent());

    }

    @Override
    public List<Note> queryviewnnumTop3(Long destId) {
        return  lambdaQuery().eq(Note::getDestId, destId)
                .orderByDesc(Note::getViewnum)
                .last("limit 3")
                .list();
    }

    @Override
    public Map<String, Object> collect(Long id) {
        //获取当前登录用户
        Long userId = SecurityContextHolder.getUserId();
        //当前用户收藏的key
        String key = RedisKeys.USER_NOTE_FAVOR.join(userId.toString());
        //判断redis中是否存在用户收藏的key，不存在时创建,因为HashSet<>里没有数据时，
        // 会自动删除掉所有key，所以要保证里面有数据，存储了一个-1L
        if (!redisService.hasKey(key)) {
            HashSet<Long> ids = new HashSet<>();
            ids.add(-1L);
            redisService.setCacheSet(key,ids);
        }
        boolean b = false;
        String haskey = RedisKeys.NOTE_STATIS_HASH.join(id.toString());
        if (redisService.isCacheSetContains(key,id)){
            //取消收藏
            redisService.incrementCacheMapValue(haskey,"favornum",-1);
            //删除我的收藏里的id，也就是文档ID
            redisService.deleteCacheSetValue(key,id);
        }else{
            //添加收藏
            redisService.incrementCacheMapValue(haskey,"favornum",1);
            redisService.addCacheSetValue(key,id);
            b = true;
        }
        Map<String, Object> cacheMap = redisService.getCacheMap(haskey);
        cacheMap.put("collectStatus",b);
        return cacheMap;

    }

    @Override
    public void noteStatisHashPersistence() {
        String hashKey = RedisKeys.NOTE_STATIS_HASH.join("*");
        Collection<String> keys = redisService.keys(hashKey);
        if (keys != null && keys.size() > 0) {
            for (String key : keys) {
                Map<String, Object> cacheMap = redisService.getCacheMap(key);
                lambdaUpdate().eq(Note::getId,cacheMap.get("id"))
                        .set(Note::getViewnum,cacheMap.get("viewnum"))
                        .set(Note::getSharenum,cacheMap.get("sharenum"))
                        .set(Note::getReplynum,cacheMap.get("replynum"))
                        .set(Note::getFavornum,cacheMap.get("favornum"))
                        .set(Note::getThumbsupnum,cacheMap.get("thumbsupnum"))
                        .update();
            }
        }
    }

    @Override
    public Map<String, Object> star(Long id) {
        //注入uid
        Long uid = SecurityContextHolder.getUserId();
        //拼key
        String key = RedisKeys.USER_NOTE_THUMBSUP.join(uid.toString(), id.toString());

        //计算过期时间
        Date now = new Date();
        Date endDate = DateUtil.getEndDate(now);
        Long seconde = DateUtil.getDateBetween(now, endDate);

        //判断redis中是否有key， 如果没有创建key设置值0
        if( ! redisService.hasKey(key)){
            redisService.setCacheObject(key, 0, seconde, TimeUnit.SECONDS);
        }
        //点赞次数++
        Long ret = redisService.incrementCacheObjectValue(key, 1);

        String hashKey = RedisKeys.NOTE_STATIS_HASH.join(id.toString());

        //判断点赞次数，如果大于3，设置result为false
        boolean result = false;
        //如果小于等于3，设置result为true
        if(ret <= 3) {
            result = true;
            redisService.incrementCacheMapValue(hashKey, "thumbsupnum", 1);
        }

        //查询统计数字map结构，并将result加入到map中
        Map<String, Object> cacheMap = redisService.getCacheMap(hashKey);
        cacheMap.put("result", result);
        //返回map
        return cacheMap;
    }

    @Override
    public Boolean isUserFavor(Long uid, Long sid) {
        String key = RedisKeys.USER_NOTE_FAVOR.join(uid.toString());
        if (!redisService.hasKey(key)) {
            HashSet<Long> sids = new HashSet<>();
            sids.add(-1L);
            redisService.setCacheSet(key,sids);
        }
        return redisService.isCacheSetContains(key,sid);
    }

    @Override
    public Map<String, Object> viewnumIncr(Long nid) {
        String key = noteKeyHsahInit(nid);
        redisService.incrementCacheMapValue(key, "viewnum", 1);
        return redisService.getCacheMap(key);

    }
    private String noteKeyHsahInit (Long nid){
        String key = RedisKeys.NOTE_STATIS_HASH.join(nid.toString());
        //判断布隆过滤器后进行查询
        //不加会产生穿透
        if (!redisService.hasKey(key)) {
            Note note = this.getById(nid);
            Map<String, Object> map = new HashMap<>();
            map.put("viewnum", Integer.valueOf(note.getViewnum().toString()));
            map.put("replynum", Integer.valueOf(note.getReplynum().toString()));
            map.put("sharenum", Integer.valueOf(note.getSharenum().toString()));
            map.put("favornum", Integer.valueOf(note.getFavornum().toString()));
            map.put("thumbsupnum", Integer.valueOf(note.getThumbsupnum().toString()));
            map.put("id", note.getId());
            redisService.setCacheMap(key, map);
        }
        return key;
    }
}
